package co.baiku.boot.common.type;

import co.baiku.boot.common.tools.StringTools;
import co.baiku.boot.common.validate.Validation;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;

public enum TimeFormat {
    /**
     * yyyy-MM
     */
    MONTH("yyyy-MM"),
    /**
     * yyyy-MM-dd
     */
    DATE("yyyy-MM-dd"),
    /**
     * HH:mm:ss
     */
    TIME("HH:mm:ss"),
    /**
     * yyyy-MM-dd HH:mm:ss
     */
    DATETIME("yyyy-MM-dd HH:mm:ss"),
    /**
     * yyyyMMdd
     */
    DATE_NOTLINE("yyyyMMdd"),
    /**
     * yyyyMMddHHmmss
     */
    DATETIME_NOTLINE("yyyyMMddHHmmss");

    String pattern;

    TimeFormat(String pattern) {
        this.pattern = pattern;
    }

    public String getPattern() {
        return pattern;
    }

    public void setPattern(String pattern) {
        this.pattern = pattern;
    }

    /**
     * 时间转字符串
     *
     * @param time   时间
     * @param format 格式
     * @return
     */
    public static String toStr(LocalDateTime time, TimeFormat format) {
        return time.format(DateTimeFormatter.ofPattern(format.pattern));
    }

    /**
     * 自定义格式-时间转字符串
     * @param time 时间
     * @param pattern 格式
     * @return
     */
    public static String toStr(LocalDateTime time, String pattern){
        return time.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 日期转字符串
     *
     * @param time   时间
     * @param format 格式
     * @return
     */
    public static String toStr(LocalDate time, TimeFormat format) {
        return toStr(time.atTime(0, 0), format);
    }

    /**
     * 字符串转时间
     *
     * @param time   时间字符串
     * @param format 格式
     * @return LocalDateTime
     */
    public static LocalDateTime toTime(String time, TimeFormat format) {
        if (format == DATETIME || format == DATETIME_NOTLINE) {
            return toTime(time, format.pattern);
        }
        return toDate(time, format.pattern).atTime(0, 0);
    }

    /**
     * 字符串转时间
     *
     * @param time   时间字符串
     * @param format 格式
     * @return LocalDateTime
     */
    public static LocalDateTime toTime(String time, String format) {
        if (StringTools.isNotBlank(time) && time.length() != format.length()) {
            throw Validation.error("时间格式不正确,预期:" + format + ",实际:" + time);
        }
        return LocalDateTime.parse(time, DateTimeFormatter.ofPattern(format));
    }

    /**
     * 字符串转日期
     *
     * @param time   时间字符串
     * @param format 格式
     * @return LocalDate
     */
    public static LocalDate toDate(String time, TimeFormat format) {
        return toDate(time, format.pattern);
    }

    /**
     * 字符串转日期
     *
     * @param time   时间字符串
     * @param format 格式
     * @return LocalDate
     */
    public static LocalDate toDate(String time, String format) {
        if (StringTools.isNotBlank(time) && time.length() != format.length()) {
            throw Validation.error("时间格式不正确,预期:" + format + ",实际:" + time);
        }
        return LocalDate.parse(time, DateTimeFormatter.ofPattern(format));
    }

    /**
     * 从date类型转为 LocalDateTime
     *
     * @param date date时间
     * @return LocalDateTime
     */
    public static LocalDateTime fromDate(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * 当天的最小时间，将时间的时分秒都清为0
     *
     * @param time 时间
     * @return 当天的最小时间
     */
    public static LocalDateTime toOrigin(LocalDateTime time) {
        return time.withHour(0).withMinute(0).withSecond(0).withNano(0);
    }

    /**
     * 当天的最大时间，将时间的时分秒都设置为最大值
     *
     * @param time 时间
     * @return 当天的最大时间
     */
    public static LocalDateTime toTerminus(LocalDateTime time) {
        return time.withHour(23).withMinute(59).withSecond(59).withNano(999999999);
    }

    /**
     * 转为java.util.Date类型
     *
     * @param date LocalDateTime时间
     * @return Date
     */
    public static Date toDate(LocalDateTime date) {
        return Date.from(date.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static long toSecond(LocalDateTime datetime) {
        return datetime.toEpochSecond(systemDefaultZoneOffset());
    }

    public static long toMilliSecond(LocalDateTime datetime) {
        return datetime.toInstant(systemDefaultZoneOffset()).toEpochMilli();
    }

    public static Duration between(LocalDateTime startTime, LocalDateTime endTime) {
        return Duration.between(startTime, endTime);
    }

    public static ZoneOffset systemDefaultZoneOffset() {
        return OffsetDateTime.now(ZoneId.systemDefault()).getOffset();
    }

}
